package vn.com.bookstore.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import vn.com.bookstore.dao.TransactionDao;
import vn.com.bookstore.domain.model.AudioBook;
import vn.com.bookstore.domain.model.Customer;
import vn.com.bookstore.domain.model.PagingInfo;
import vn.com.bookstore.domain.model.Publisher;
import vn.com.bookstore.domain.model.SearchResult;
import vn.com.bookstore.model.vo.AmountVO;
import vn.com.bookstore.model.vo.TransactionVO;
import vn.com.bookstore.service.AudioBookService;
import vn.com.bookstore.service.BooksOnlineService;
import vn.com.bookstore.service.CustomerService;
import vn.com.bookstore.utils.DataHelper;
import vn.com.bookstore.utils.DataHelper.Paging;
import vn.com.bookstore.utils.PaypalHelper;

@Controller
public class AudioBookController {
	
	private static final Logger LOGGER = Logger.getLogger(AudioBookController.class);
	
	@Autowired
	private AudioBookService audioBookService;
	
	@Autowired
	private BooksOnlineService booksOnlineService; 
	
	@Autowired
	private TransactionDao transactionDao;
	
	@Autowired
	private CustomerService customerService;
	
	@Value("${hostname.url}")
	public String HOSTNAME_URL;
	
	@Value("${upload.auio.image.url.server}")
	private String URL_ROOT_FOLDER_UPLOAD_AUDIO;
	
	@RequestMapping(value="online/view-audio-book", method=RequestMethod.GET)
	public String viewAudioBook(Model model) {
		PagingInfo pagingInfo = new PagingInfo(Paging.OFFSET.getValue(), 1);
		SearchResult<AudioBook> result = audioBookService.getAudioBook(pagingInfo);
		List<AudioBook> audioBooks = new ArrayList<AudioBook>();
		if(result != null  && result.getSearchResult() != null) {
			audioBooks = result.getSearchResult();
		}
		
		model.addAttribute("audioBooks", audioBooks);
		model.addAttribute("pagingInfo", result.getPagingInfo());
		return "website/audio/view-audio-book";
	}
	
	@RequestMapping(value = "/online/searchAudioBooks", method = RequestMethod.POST)
	public String searchAudioBooks(Model model,
			@RequestParam("keyword") String keyword) {
		PagingInfo pagingInfo = new PagingInfo(Paging.OFFSET.getValue(), 1);
		SearchResult<AudioBook> result = audioBookService.getAudioBookWithKeyWord(keyword, pagingInfo);
		model.addAttribute("audioBooks", result.getSearchResult());
		model.addAttribute("keyword", keyword);
		model.addAttribute("pagingInfo", result.getPagingInfo());
		return "website/audio/view-audio-book";
	}
	
	@RequestMapping(value = "/online/ajax/getMoreAudioBooks", method = RequestMethod.POST)
	public @ResponseBody
	ModelAndView getMoreBooksByKeyword(@RequestParam("keyword") String keyword,
			@RequestParam("pageIndex") int pageIndex) {
		ModelAndView model = new ModelAndView(
				"website/audio/view-more-audio-book");
		PagingInfo pagingInfo = new PagingInfo(Paging.OFFSET.getValue(), pageIndex);
		SearchResult<AudioBook> result = audioBookService.getAudioBookWithKeyWord(keyword, pagingInfo);
		model.addObject("audioBooks", result.getSearchResult());
		model.addObject("pagingInfo", result.getPagingInfo());
		return model;
	}
	
	@RequestMapping(value = "/online/buy-audio", method = RequestMethod.GET)
	public String openPayment(Model model, @RequestParam("index") Integer bookId) {
		AudioBook book = audioBookService.getAudioBookById(bookId);
		String fileName = book.getUrlAudio().substring(
				book.getUrlAudio().lastIndexOf("/") + 1);
		Publisher publisher = booksOnlineService.getPublisherByid(book.getPublisherId());
		model.addAttribute("bookInfo", book);
		model.addAttribute("publisherInfo", publisher);
		model.addAttribute("fileName", fileName);
		return "website/payment/audio-payment";
	}
	
	@SuppressWarnings({ "rawtypes", "unused" })
	@RequestMapping(value = "/online/payment-audio", method = RequestMethod.GET)
	public String payment(Model model, HttpServletRequest request,
			HttpServletResponse response, @RequestParam("id") int id) {

		AudioBook book = audioBookService.getAudioBookById(id);

		String returnUrl = HOSTNAME_URL
				+ "/book-store/online/download-audio?id=" + id;
		String cancelUrl = HOSTNAME_URL + "/book-store/online/home";

		PaypalHelper paypalHelper = new PaypalHelper();
		HashMap nvp = paypalHelper.CallShortcutExpressCheckout(book, returnUrl,
				cancelUrl);
		String ErrorCode = StringUtils.EMPTY;
		String ErrorShortMsg = StringUtils.EMPTY;
		String ErrorLongMsg = StringUtils.EMPTY;
		String ErrorSeverityCode = StringUtils.EMPTY;
		String strAck = "";
		if (nvp != null) {
			strAck = nvp.get("ACK").toString();
			if (strAck != null && strAck.equalsIgnoreCase("Success")) {
				model.addAttribute("tokenPaypal", nvp.get("TOKEN").toString());
				HttpSession session = request.getSession();
				session.setAttribute("token", nvp.get("TOKEN").toString());
				String tokenSession = (String) request.getSession()
						.getAttribute("token");
				// ' Redirect to paypal.com
				try {
					String s = paypalHelper.getPAYPAL_URL()
							+ nvp.get("TOKEN").toString();
					response.sendRedirect(paypalHelper.getPAYPAL_URL()
							+ nvp.get("TOKEN").toString());
				} catch (IOException e) {
					LOGGER.info(e);
				}
			} else {
				// Display a user friendly Error on the page using any of the
				// following error information returned by PayPal

				ErrorCode = nvp.get("L_ERRORCODE0").toString();
				ErrorShortMsg = nvp.get("L_SHORTMESSAGE0").toString();
				ErrorLongMsg = nvp.get("L_LONGMESSAGE0").toString();
				ErrorSeverityCode = nvp.get("L_SEVERITYCODE0").toString();

				LOGGER.info("nvp: "+nvp.toString());
				LOGGER.info(ErrorCode + ":" + ErrorShortMsg + ":" +
				 ErrorLongMsg + ":" + ErrorSeverityCode);

				return ErrorLongMsg;

			}
		}

		return null;
	}
	
	@RequestMapping(value = "online/ajax/check-valid-amount-buy-audio", method = RequestMethod.POST)
	public @ResponseBody AmountVO checkValidAmountNganLuong(@RequestParam("bookId") Integer bookId) {
		AmountVO amountVO = new AmountVO();
		AudioBook book = audioBookService.getAudioBookById(bookId);
		SecurityContext context = SecurityContextHolder.getContext();
		String username = context.getAuthentication().getName();
		Customer customer = customerService.getCustomerByUsername(username);
		double priceBook = computeRealPriceAudio(book);
		if (book == null || customer == null || priceBook > customer.getPointCart()) {
			amountVO.setCanBuyBook(false);
		}else{
			amountVO.setCanBuyBook(true);
		}
		if(customer != null){
			amountVO.setMoney(customer.getPointCart());
		}
		LOGGER.info("amountVO: "+amountVO.getMoney());
		return amountVO;
	}
	
	@RequestMapping(value = "/online/download-audio", method = RequestMethod.GET)
	public void downloadFile(@RequestParam("id") int id,
			HttpServletResponse response, HttpServletRequest request) {
		String tokenRequest = request.getParameter("token");
		String tokenSession = (String) request.getSession().getAttribute(
				"token");
		if (tokenRequest != null) {
			if (tokenRequest.equals(tokenSession)) {
				request.getSession().removeAttribute("token");
				// get username
				SecurityContext context = SecurityContextHolder.getContext();
				String username = context.getAuthentication().getName();
				int customerId = customerService.getCustomerByUsername(username).getId();

				// save transaction
				AudioBook book = audioBookService.getAudioBookById(id);
				saveCustomerTransaction(id, customerId, book, DataHelper.TransactionType.PAYPAL.getCode());
				
				// download
				downloadAudio(response, book);
			} else {
				LOGGER.info("error Token ");
			}
		} else {
			LOGGER.info("Token null ");
		}

	}
	
	@RequestMapping(value = "/online/nganluong/download-audio", method = RequestMethod.GET)
	public void downloadFileWithNganLuong(@RequestParam("index") int id,
			HttpServletResponse response, HttpServletRequest request) {
		AmountVO amountVO = checkValidAmountNganLuong(id);
		if(!amountVO.isCanBuyBook()){
			return;
		}
		// get username
		SecurityContext context = SecurityContextHolder.getContext();
		String username = context.getAuthentication().getName();
		int customerId = customerService.getCustomerByUsername(username).getId();
		
		AudioBook book = audioBookService.getAudioBookById(id);
		double priceBook = computeRealPriceAudio(book);
		Customer customer = customerService.getCustomerByUsername(username);
		// save transaction
		book.setPrice(priceBook);//set real price for transaction 
		saveCustomerTransaction(id, customerId, book, DataHelper.TransactionType.NGANLUONG.getCode());
		//Subtract amount of customer
		updateCustomerPointCart(priceBook, customer);
		
		// download
		downloadAudio(response, book);
	}

	private void updateCustomerPointCart(double priceBook, Customer customer) {
		customer.setPointCart(customer.getPointCart() - priceBook);
		customerService.updateAmountOfCustomer(customer);
	}

	private double computeRealPriceAudio(AudioBook book) {
		double priceBook = book.getPrice();
		if(book.getDiscount() > 0) {
			priceBook = priceBook - (priceBook*book.getDiscount()/100);
		}
		return priceBook;
	}

	private void downloadAudio(HttpServletResponse response, AudioBook book) {
		String urlFile = book.getUrlAudio();
		String uri = URL_ROOT_FOLDER_UPLOAD_AUDIO + urlFile;
		String fileTypeCurrent = uri.substring(uri.lastIndexOf(".")+1);
		String contentType = "audio/"+fileTypeCurrent+"; charset=UTF-8";
		String fileName = book.getUrlAudio().substring(
				book.getUrlAudio().lastIndexOf("/") + 1);
		try {
			File file = new File(uri);
			response.setContentType(contentType);
			response.setCharacterEncoding("UTF-8");
			response.setContentLength(new Long(file.length()).intValue());
			response.setHeader(
					"Content-Disposition",
					"attachment; filename="
							+ URLEncoder.encode(fileName.replace(" ", "-"), "UTF-8"));
			FileCopyUtils.copy(new FileInputStream(file),
					response.getOutputStream());
		} catch (Exception e) {
			LOGGER.info("downloadFile : " + e.getMessage());
		}
	}

	private void saveCustomerTransaction(int id, int customerId, AudioBook book, String type) {
		TransactionVO transactionVO = new TransactionVO();
		transactionVO.setCustomerId(customerId);
		transactionVO.setTotalPrice(book.getPrice());
		transactionVO.setTransactionDate(new Date());
		transactionVO.setTransaction_type(type);
		transactionVO.setAudioBookId(id);
		transactionDao.saveTransaction(transactionVO);
	}
}
